home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #2 / Ham Radio 2000 - Volume 2.iso / HAMV2 / TCP_IP / TNOS230S / SLIP.C < prev    next >
Encoding:
C/C++ Source or Header  |  1997-09-06  |  7.7 KB  |  337 lines

  1. /* SLIP (Serial Line IP) encapsulation and control routines.
  2.  * Copyright 1991 Phil Karn
  3.  *
  4.  * Van Jacobsen header compression hooks added by Katie Stevens, UC Davis
  5.  *
  6.  *    - Feb 1991    Bill_Simpson@um.cc.umich.edu
  7.  *            reflect changes to header compression calls
  8.  *            revise status display
  9.  */
  10. #include "global.h"
  11. #include "mbuf.h"
  12. #include "iface.h"
  13. #include "slhc.h"
  14. #include "slip.h"
  15. #include "trace.h"
  16. #include "commands.h"
  17.  
  18. #if !defined(_lint)
  19. static char rcsid[] OPTIONAL = "$Id: slip.c,v 1.19 1997/09/07 00:31:16 root Exp root $";
  20. #endif
  21.  
  22. static struct mbuf *slip_decode (struct slip * sp, unsigned char c);
  23. static struct mbuf *slip_encode (struct mbuf * bp, int usecrc);
  24.  
  25. /* Slip level control structure */
  26. struct slip *Slip;
  27.  
  28. /* Send routine for point-to-point slip */
  29. int
  30. slip_send (bp, iface, gateway, prec, del, tput, rel)
  31. struct mbuf *bp;        /* Buffer to send */
  32. struct iface *iface;        /* Pointer to interface control block */
  33. uint32 gateway OPTIONAL;    /* Ignored (SLIP is point-to-point) */
  34. int prec OPTIONAL;
  35. int del OPTIONAL;
  36. int tput OPTIONAL;
  37. int rel OPTIONAL;
  38. {
  39. #ifdef VJCOMPRESS
  40. register struct slip *sp;
  41. int type;
  42. #endif
  43.  
  44.     if (iface == NULLIF) {
  45.         free_p (bp);
  46.         return -1;
  47.     }
  48. #ifdef VJCOMPRESS
  49.     sp = &Slip[iface->xdev];
  50.     if (sp->escaped & SLIP_VJCOMPR) {
  51.         /* Attempt IP/ICP header compression */
  52.         type = slhc_compress (sp->slcomp, &bp, TRUE);
  53.         bp->data[0] |= uchar (type);
  54.     }
  55. #endif
  56.     return (*iface->raw) (iface, bp);
  57. }
  58.  
  59.  
  60. /* Send a raw slip frame */
  61. int
  62. slip_raw (iface, bp)
  63. struct iface *iface;
  64. struct mbuf *bp;
  65. {
  66. struct mbuf *bp1;
  67. struct slip *sp;
  68.  
  69.     sp = &Slip[iface->xdev];
  70.     if (sp->usecrc == 0 || sp->tracepoll == 1 || bp->cnt != 2 || ((*bp->data & 0x0f) != 0x0e))
  71.         dump (iface, IF_TRACE_OUT, (unsigned) sp->type, bp);
  72.     iface->rawsndcnt++;
  73.     iface->lastsent = secclock ();
  74.  
  75. #if 1
  76.     if (iface->flags & LOOPBACK_AX25)    {
  77.         (void) pullchar (&bp);
  78.         if (net_route (iface, 9, bp) != 0)
  79.             free_p (bp);
  80.         return 0;
  81.     }
  82. #endif
  83.     if ((bp1 = slip_encode (bp, sp->usecrc)) == NULLBUF)
  84.         return -1;
  85.  
  86.     if (iface->trace & IF_TRACE_RAW)
  87.         raw_dump (iface, -1, bp1);
  88.     return sp->send (iface->dev, bp1);
  89. }
  90.  
  91.  
  92. /* Encode a packet in SLIP format */
  93. static
  94. struct mbuf *
  95. slip_encode (bp, usecrc)
  96. struct mbuf *bp;
  97. int usecrc;
  98. {
  99. struct mbuf *lbp;    /* Mbuf containing line-ready packet */
  100. register unsigned char *cp;
  101. int c, crc, done;
  102. struct mbuf **bpp = &bp;
  103.  
  104.     /* Allocate output mbuf that's twice as long as the packet.
  105.      * This is a worst-case guess (consider a packet full of FR_ENDs!)
  106.      */
  107.     lbp = alloc_mbuf ((int16) ((2 * len_p (bp)) + 3));
  108.     if (lbp == NULLBUF) {
  109.         /* No space; drop */
  110.         free_p (bp);
  111.         return NULLBUF;
  112.     }
  113.     cp = lbp->data;
  114.  
  115.     /* Flush out any line garbage */
  116.     *cp++ = FR_END;
  117.  
  118.     /* Set crc to zero */
  119.     crc = 0;
  120.     done = 0;
  121.  
  122.  
  123.     /* Copy input to output, escaping special characters */
  124.     while (1) {        /*lint !e716 !e774 */
  125.         c = PULLCHAR (bpp);
  126.         if (c == -1) {    /* If we reached the end of the data */
  127.             if (!usecrc)    /* and we don't use a CRC, */
  128.                 break;    /* we're done... */
  129.             c = crc;/* otherwise, encode the crc as well */
  130.             done = 1;
  131.         } else        /* A regular data char, calculate crc */
  132.             crc ^= c;
  133.         switch (c) {
  134.             case FR_ESC:
  135.                 *cp++ = FR_ESC;
  136.                 *cp++ = T_FR_ESC;
  137.                 break;
  138.             case FR_END:
  139.                 *cp++ = FR_ESC;
  140.                 *cp++ = T_FR_END;
  141.                 break;
  142.             default:
  143.                 *cp++ = uchar (c);
  144.         }
  145.         if (done)
  146.             break;
  147.     }
  148.     *cp++ = FR_END;
  149.     lbp->cnt = (int16) (cp - lbp->data);
  150.     return lbp;
  151. }
  152.  
  153.  
  154. /*lint -esym(18,slip_decode) */
  155. /* Process incoming bytes in SLIP format
  156.  * When a buffer is complete, return it; otherwise NULLBUF
  157.  */
  158. static struct mbuf *
  159. slip_decode (sp, c)
  160. register struct slip *sp;
  161. unsigned char c;        /* Incoming character */
  162. {
  163. struct mbuf *bp;
  164. #ifdef POLLEDKISS
  165. struct mbuf *bp1;
  166. #endif
  167.  
  168.     switch (uchar (c)) {
  169.         case FR_END:
  170.             bp = sp->rbp_head;
  171.             sp->rbp_head = NULLBUF;
  172. #ifdef POLLEDKISS
  173.             if (sp->polled) {
  174.                 sp->rx = 0;
  175.                 ksignal (&sp->rx, 1);    /* tell the poller we're done */
  176.             }
  177.             if (sp->usecrc) {
  178.                 if (bp) {
  179.                     /* Check the crc. After an ex-or of data and checksum
  180.                      * the result should be 0 - WG7J
  181.                      */
  182.                     if (sp->rxcrc) {
  183.                         free_p (bp);
  184.                         bp = NULLBUF;
  185.                     }
  186.                     /* If valid, delete the crc byte from the data */
  187.                     /* If the length of the last mbuf in chain becomes
  188.                      * zero, we must delete it. Otherwise upper level code
  189.                      * thinks we lost connection - OH2BNS
  190.                      */
  191.                     else if (--sp->rbp_tail->cnt == 0) {
  192.                         for (bp1 = bp; bp1->next->cnt != 0; bp1 = bp1->next) ;
  193.                         free_p (bp1->next);
  194.                         bp1->next = NULLBUF;
  195.                     }
  196.                 }
  197.             }
  198. #endif
  199.             return bp;    /* Will be NULLBUF if empty frame */
  200.         case FR_ESC:
  201.             sp->escaped |= SLIP_FLAG;
  202.             return NULLBUF;
  203.         default:
  204.             break;
  205.     }
  206.     if (sp->escaped & SLIP_FLAG) {
  207.         /* Translate 2-char escape sequence back to original char */
  208.         sp->escaped &= ~SLIP_FLAG;
  209.         switch (uchar (c)) {
  210.             case T_FR_ESC:
  211.                 c = FR_ESC;
  212.                 break;
  213.             case T_FR_END:
  214.                 c = FR_END;
  215.                 break;
  216.             default:
  217.                 sp->errors++;
  218.                 break;
  219.         }
  220.     }
  221.     /* We reach here with a character for the buffer;
  222.      * make sure there's space for it
  223.      */
  224.     if (sp->rbp_head == NULLBUF) {
  225.         /* Allocate first mbuf for new packet */
  226.         if ((sp->rbp_tail = sp->rbp_head = alloc_mbuf (SLIP_ALLOC)) == NULLBUF)
  227.             return NULLBUF;    /* No memory, drop */
  228.         sp->rcp = (char *) sp->rbp_head->data;
  229. #ifdef POLLEDKISS
  230.         /* If polled kiss, signal poller that we are receiving a packet */
  231.         if (sp->polled)
  232.             sp->rx = 1;
  233.         if (sp->usecrc)    /* clear the crc - WG7J */
  234.             sp->rxcrc = 0;
  235. #endif
  236.     } else if (sp->rbp_tail->cnt == SLIP_ALLOC) {
  237.         /* Current mbuf is full; link in another */
  238.         if ((sp->rbp_tail->next = alloc_mbuf (SLIP_ALLOC)) == NULLBUF) {
  239.             /* No memory, drop whole thing */
  240.             free_p (sp->rbp_head);
  241.             sp->rbp_head = NULLBUF;
  242.             return NULLBUF;
  243.         }
  244.         sp->rbp_tail = sp->rbp_tail->next;
  245.         sp->rcp = (char *) sp->rbp_tail->data;
  246.     }
  247.     /* Store the character, increment fragment and total
  248.      * byte counts
  249.      */
  250.     *sp->rcp++ = (char) c;
  251.     sp->rbp_tail->cnt++;
  252. #ifdef POLLEDKISS
  253.     /* If this interface uses CRC, adjust the crc */
  254.     if (sp->usecrc)
  255.         sp->rxcrc ^= (char) c;
  256. #endif
  257.     return NULLBUF;
  258. }
  259.  
  260.  
  261. /* Process SLIP line input */
  262. void
  263. asy_rx (xdev, p1, p2)
  264. int xdev;
  265. void *p1 OPTIONAL;
  266. void *p2 OPTIONAL;
  267. {
  268. int c;
  269. struct mbuf *bp = (struct mbuf *) 0;
  270. register struct slip *sp;
  271. int cdev;
  272.  
  273.     server_disconnect_io ();
  274.     sp = &Slip[xdev];
  275.     cdev = sp->iface->dev;
  276.  
  277.     while ((c = sp->get (cdev)) != -1) {
  278.         if ((bp = slip_decode (sp, uchar(c))) == NULLBUF)
  279.             continue;    /* More to come */
  280. #ifdef VJCOMPRESS
  281.         if (sp->iface->trace & IF_TRACE_RAW)
  282.             raw_dump (sp->iface, IF_TRACE_IN, bp);
  283.  
  284.         if (sp->escaped & SLIP_VJCOMPR) {
  285.             if ((c = bp->data[0]) & SL_TYPE_COMPRESSED_TCP) {
  286.                 if (slhc_uncompress (sp->slcomp, &bp) <= 0) {
  287.                     free_p (bp);
  288.                     sp->errors++;
  289.                     continue;
  290.                 }
  291.             } else if (c >= SL_TYPE_UNCOMPRESSED_TCP) {
  292.                 bp->data[0] &= 0x4f;
  293.                 if (slhc_remember (sp->slcomp, &bp) <= 0) {
  294.                     free_p (bp);
  295.                     sp->errors++;
  296.                     continue;
  297.                 }
  298.             }
  299.         }
  300. #endif
  301.         if (net_route (sp->iface, sp->type, bp) != 0) {
  302.             free_p (bp);
  303.             bp = 0;
  304.         }
  305.     }
  306.     if (bp)
  307.         free_p (bp);
  308. }
  309.  
  310.  
  311.  
  312. /* Show serial line status */
  313. void
  314. slip_status (iface)
  315. struct iface *iface;
  316. {
  317. struct slip *sp;
  318.  
  319.     if (iface->xdev > SLIP_MAX)
  320.         /* Must not be a SLIP device */
  321.         return;
  322.  
  323.     sp = &Slip[iface->xdev];
  324.     if (sp->iface != iface)
  325.         /* Must not be a SLIP device */
  326.         return;
  327.  
  328.     tprintf ("   IN:   %lu pkts\n", iface->rawrecvcnt);
  329. #ifdef VJCOMPRESS
  330.     slhc_i_status (sp->slcomp);
  331. #endif
  332.     tprintf ("  OUT:   %lu pkts\n", iface->rawsndcnt);
  333. #ifdef VJCOMPRESS
  334.     slhc_o_status (sp->slcomp);
  335. #endif
  336. }
  337.